Inner class

Inner class(내부 클래스)
inner class는 말 그대로 “클래스 내부에 선언한 클래스” 이다.
이는 외부 클래스와 밀접한 관련이 있거나, 다른 외부 클래스와 협력할 일이 없는 경우에 사용한다.
class ABC{ //
class In{ //
static class SIn{ //
}
}
public void abc(){
class Local{ //
}
}
}
내부클래스에는
인스턴스 내부 클래스, 정적 내부 클래스, 지역 내부 클래스, 익명 내부 클래스가 있다.
    -Instance inner class
내부 클래스는 인스턴스 변수를 선언할 때와 같은 위치에 선언하며,
외부 클래스 내부에서만 생성하여 사용하는 객체를 선언할 때 쓴다.
(다른 외부 클래스에서 사용할 일이 없는 경우 내부 인스턴스 클래스로 정의)
InnerTest.java
package innerclass;
//
class OutClass {
private int num=10;
private static int sNum=20;
//
private InClass inClass;
//
public OutClass() {
inClass=new InClass();
}
class InClass{
int inNum=100;
// static
void inTest() {
System.out.println("OutCLass num= "+num+"( )");
System.out.println("OutCLass sNum= "+sNum+"( )");
}
// static
}
public void usingClass() {
inClass.inTest();
}
}
public class InnerTest{
public static void main(String[] args) {
OutClass outClass=new OutClass();
System.out.println(" ");
outClass.usingClass();
}
}
외부 클래스가 선언된 이후에 내부 클래스가 선언되어야 한다.
따라서 클래스의 생성과 상관없이 사용할 수 있는 정적 변수는 인스턴스 내부 클래스에서 선언할 수 없다.
private 이 아닌 내부클래스의 경우 외부 클래스가 아닌 다른 클래스에서도
아래와 같이 내부 클래스를 생성할 수 있다.
OutClass outClass=new OutClass();
OutCLass.InClass inClass=OutClass.new InClass();
따라서 어떤 클라스 내부에서만 사용할 목적이라면 내부 클래스를
private으로 선언해야 한다.
    -static inner class
내부 클래스가 외부 클래스 생성과 무관하게 사용할 수 있어야 하고,
정적 변수도 사용할 수 있어야 한다면 정적 내부 클래스를 사용하면 된다.
InnerTest.java
package innerclass;
class OutClass {
private int num=10;
private static int sNum=20;
static class InStaticClass{
int inNum=10;
static int sInNum=20;
//
void inTest() {
// .
System.out.println("InStaticClass inNum= "+inNum+"( )");
System.out.println("InStaticClass sInNum= "+sInNum+"( )");
System.out.println("OutClass sNum= "+sNum+"( ");
}
//
static void sTest() {
// .
System.out.println("OutClass sNum= "+sNum+"( ");
System.out.println("InStaticClass sInNum= "+sInNum+"( )");
}
}
}
public class InnerTest{
public static void main(String[] args) {
OutClass.InStaticClass sInClass=new OutClass.InStaticClass();
System.out.println(" ");
sInClass.inTest();
System.out.println();
System.out.println(" ");
OutClass.InStaticClass.sTest();
}
}
정적 내부 클래스는 외부 클래스를 생성하지 않고 바로 정적 내부 클래스 생성 가능하다.
정적 내부 클래스 메서드 변수 유형 사용 가능 여부
일반 메서드
void inTest()
외부 클래스의 인스턴스 변수(num) X
외부 클래스의 정적 변수(sNum) O
정적 내부 클래스의 인스턴스 변수(inNum) O
정적 내부 클래스의 정적 변수(sInNum) O
정적 메서드
static void aTest()
외부 클래스의 인스턴스 변수(num) X
외부 클래스의 정적 변수(sNum) O
정적 내부 클래스의 인스턴스 변수(inNum) X
정적 내부 클래스의 정적 변수(sInNum) O
정적 내부 클래스는 외부 클래스를 생성하지 않고도 내부 클래스 자료형으로 바로 선언하여 생성할 수 있다.
OutClass.InStaticClass sInClass=new OutClass.InStaticClass();
또한 정적 내부 클래스에 선언한 메서드나 변수가 private이 아닌 경우 다른 클래스에서 바로 사용할 수 있다.
OutClass.InstaticClass.sTest();
    -Local inner class
지역 내부 클래스는 지역 변수처럼 메서드 내부에 클래스를 정의하여 사용하는 것을 말한다.
LocalInnerTest.java
package innerclass;
class Outer{
int outNum=100;
static int sNum=200;
Runnable getRunnable(int i) {
int num=100;
//
class MyRunnable implements Runnable{
int localNum=100;
@Override
public void run() {
// num .
// i .
System.out.println("i ="+i);
System.out.println("num= "+num);
System.out.println("localNum= "+localNum);
System.out.println("outNum= "+outNum+"( ");
System.out.println("Outer.sNum= "+Outer.sNum+"( )");
}
}
return new MyRunnable();
}
}
public class LocalInnerTest {
public static void main(String[] args) {
Outer out=new Outer();
Runnable runner=out.getRunnable(10);
runner.run();
}
}
지역 내부 클래스에서는 지역 변수와 매개변수가 상수로 바뀌므로 변경할 수 없다.

java 7 이전에는 지역 내부 클라스는 상수만을 처리할 수 있었다.
하지만 java 8부터는 자동으로 컴파일 할 때 final 예약어가 추가 된다.
    -Anonymous inner class
익명 클래스는 클래스 이름을 사용하지 않는 클래스이다.
아래의 코드는 이전의 LocalInnerTest.java의 MyRunnalbe(int i) 메서드를
익명 클래스로 표현한 코드이다.
package innerclass;
class Outer2{
// , Runnable
Runnable getRunnable(int i) {
int num=100;
return new Runnable() {
@Override
public void run() {
System.out.println(i);
System.out.println(num);
}
}; // (;)
}
//
Runnable runner=new Runnable() {
@Override
public void run() {
System.out.println("Runnable ");
}
}; // (;)
}
public class AnonymousInnerTest {
public static void main(String[] args) {
Outer2 out=new Outer2();
Runnable runnerable=out.getRunnable(10);
runnerable.run();
out.runner.run();
}
}
익명 내부 클래스는 예전에 자바 UI에서 이벤트를 처리하는데 많이 사용하였다.
현재는 안드로이드 프로그래밍에서 위젯의 이벤트를 처리하는 핸들러를 구현할 때 사용한다.

아래 코드는 버튼을 눌렀을 때 “hello” 메세지를 출려하는 코드이다.
(버튼을 누르면 발생하는 이벤트 핸들러는 new View.OnCLickListener() 이다.
botton1.setOnClickListener=new View.OnClickListener(){
public boolean onClick(View v){
Toast.maekText(getBaseContext(),"hello",Toast.LENGTH_LONG).show();
return treu;
}
};
종류 구현 위치 사용할 수 있는
외부 클래스 변수
생성 방법
인스턴스 내부 클래스 외부 클래스 멤버 변수와 동일 외부 인스턴스 변수
외부 전역 변수
외부 클래스를 먼저 만든
후 내부 클래스 생성
정적 내부 클래스 외부 클래스 멤버 변수와 동일 외부 전역 변수 외부 클래스와 무관하게 생성
지역 내부 클래스 메서드 내부에 구현 외부 인스턴스 변수
외부 전역 변수
메서드를 호출할 때 생성
익명 내부 클래스 메서드 내부에 구현
변수에 대입하여 직접 구현
외부 인스턴스 변수
외부 전역 변수
메서드를 호출할 때 생성되거나,
인터페이스 타입변수에 대입할
 때 new 예약어를 통해 생성